home *** CD-ROM | disk | FTP | other *** search
- /* AX25 header conversion routines
- * Copyright 1991 Phil Karn, KA9Q
- */
- #include "global.h"
- #include "mbuf.h"
- #include "ax25.h"
-
- #if !defined(_lint)
- static char rcsid[] OPTIONAL = "$Id: ax25hdr.c,v 1.7 1996/08/29 12:11:16 root Exp root $";
- #endif
-
-
- /* Convert a host-format AX.25 header into a mbuf ready for transmission */
- struct mbuf *
- htonax25 (hdr, data)
- register struct ax25 *hdr;
- struct mbuf *data;
- {
- struct mbuf *bp;
- register unsigned char *cp;
- register int16 i;
-
- if (hdr == (struct ax25 *) NULL || hdr->ndigis > MAXDIGIS)
- return NULLBUF;
-
- /* Allocate space for return buffer */
- i = (int16) (AXALEN * (2 + hdr->ndigis));
- if ((bp = pushdown (data, i)) == NULLBUF)
- return NULLBUF;
-
- /* Now convert */
- cp = bp->data; /* cp -> dest field */
-
- /* Generate destination field */
- memcpy (cp, hdr->dest, AXALEN);
- if (hdr->cmdrsp == LAPB_COMMAND)
- cp[ALEN] |= C; /* Command frame sets C bit in dest */
- else
- cp[ALEN] &= ~C;
- cp[ALEN] &= ~E; /* Dest E-bit is always off */
-
- cp += AXALEN; /* cp -> source field */
-
- /* Generate source field */
- memcpy (cp, hdr->source, AXALEN);
- if (hdr->cmdrsp == LAPB_RESPONSE)
- cp[ALEN] |= C;
- else
- cp[ALEN] &= ~C;
- /* Set E bit on source address if no digis */
- if (hdr->ndigis == 0) {
- cp[ALEN] |= E;
- return bp;
- }
- cp += AXALEN; /* cp -> first digi field */
-
- /* All but last digi get copied with E bit off */
- for (i = 0; i < hdr->ndigis; i++) {
- memcpy (cp, hdr->digis[i], AXALEN);
- if (i < hdr->ndigis - 1)
- cp[ALEN] &= ~E;
- else
- cp[ALEN] |= E; /* Last digipeater has E bit set */
- if (i < hdr->nextdigi) {
- cp[ALEN] |= REPEATED;
- } else
- cp[ALEN] &= ~REPEATED;
- cp += AXALEN; /* cp -> next digi field */
- }
- return bp;
- }
-
-
- /* Convert a network-format AX.25 header into a host format structure
- * Return -1 if error, number of addresses if OK
- */
- int
- ntohax25 (hdr, bpp)
- register struct ax25 *hdr; /* Output structure */
- struct mbuf **bpp;
- {
- register char *axp;
-
- if (pullup (bpp, (unsigned char *) hdr->dest, AXALEN) < AXALEN)
- return -1;
-
- if (pullup (bpp, (unsigned char *) hdr->source, AXALEN) < AXALEN)
- return -1;
-
- /* Process C bits to get command/response indication */
- if ((hdr->source[ALEN] & C) == (hdr->dest[ALEN] & C))
- hdr->cmdrsp = LAPB_UNKNOWN;
- else if (hdr->source[ALEN] & C)
- hdr->cmdrsp = LAPB_RESPONSE;
- else
- hdr->cmdrsp = LAPB_COMMAND;
-
- hdr->ndigis = 0;
- hdr->nextdigi = 0;
- if (hdr->source[ALEN] & E)
- return 2; /* No digis */
-
- /* Count and process the digipeaters */
- axp = hdr->digis[0];
- while (hdr->ndigis < MAXDIGIS && pullup (bpp, (unsigned char *) axp, AXALEN) == AXALEN) {
- hdr->ndigis++;
- if (axp[ALEN] & REPEATED)
- hdr->nextdigi++;
- if (axp[ALEN] & E) /* Last one */
- return hdr->ndigis + 2;
- axp += AXALEN;
- }
- return -1; /* Too many digis */
- }
-